package org.example.common.base.util.jwt;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecureDigestAlgorithm;
import org.example.common.base.constants.CacheConstants;
import org.example.common.base.constants.SecurityConstants;
import org.example.common.base.constants.TokenConstants;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;


/**
 * jwt工具类
 *
 * @author LiJY
 * @date 2024/11/28
 */
public class JwtUtils
{

    /**
     * 加密算法
     */
    private final static SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;

    /**
     * 过期时间
     */
    public final static int expireTime = CacheConstants.EXPIRATION;


    /**
     * 从数据声明生成令牌
     *
     * @param claims 数据声明
     * @return 令牌
     */
    public static String createToken(Map<String, Object> claims)
    {
        Date expireDate = DateUtil.offset(new Date(), DateField.MINUTE, expireTime);
        SecretKey KEY = Keys.hmacShaKeyFor(TokenConstants.SECRET.getBytes());
        JwtBuilder builder = Jwts.builder()
                .header()
                .add("typ", "JWT")
                .add("alg", "HS256")
                .and()
                .id(IdUtil.fastUUID())
                .expiration(expireDate)
                .issuedAt(new Date())
                .subject("Auth")
                .issuer(TokenConstants.JWT_ISS);
        // 动态添加 claims
        if (claims != null) {
            claims.forEach(builder::claim);
        }
        return builder.signWith(KEY, ALGORITHM).compact();
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    public static Claims parseToken(String token)
    {
        Jws<Claims> claimsJws = parseClaim(token);
        return claimsJws.getPayload();
    }

    /**
     * 解析token
     * @param token token
     * @return Jws<Claims>
     */
    private static Jws<Claims> parseClaim(String token) {
        SecretKey KEY = Keys.hmacShaKeyFor(TokenConstants.SECRET.getBytes());
        return Jwts.parser()
                .verifyWith(KEY)
                .build()
                .parseSignedClaims(token);
    }

    /**
     * 根据令牌获取用户标识
     *
     * @param token 令牌
     * @return 用户ID
     */
    public static String getUserKey(String token)
    {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstants.USER_KEY);
    }

    /**
     * 根据令牌获取用户标识
     *
     * @param claims 身份信息
     * @return 用户ID
     */
    public static String getUserKey(Claims claims)
    {
        return getValue(claims, SecurityConstants.USER_KEY);
    }

    /**
     * 根据令牌获取用户ID
     *
     * @param token 令牌
     * @return 用户ID
     */
    public static String getUserId(String token)
    {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstants.DETAILS_USER_ID);
    }

    /**
     * 根据身份信息获取用户ID
     *
     * @param claims 身份信息
     * @return 用户ID
     */
    public static String getUserId(Claims claims)
    {
        return getValue(claims, SecurityConstants.DETAILS_USER_ID);
    }

    /**
     * 根据令牌获取用户名
     *
     * @param token 令牌
     * @return 用户名
     */
    public static String getUserName(String token)
    {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstants.DETAILS_USERNAME);
    }

    /**
     * 根据身份信息获取用户名
     *
     * @param claims 身份信息
     * @return 用户名
     */
    public static String getUserName(Claims claims)
    {
        return getValue(claims, SecurityConstants.DETAILS_USERNAME);
    }

    /**
     * 根据身份信息获取键值
     *
     * @param claims 身份信息
     * @param key 键
     * @return 值
     */
    public static String getValue(Claims claims, String key)
    {
        return Convert.toStr(claims.get(key), "");
    }
}
